#include "chatwidget.h"
#include "ui_chatwidget.h"
#include <QDebug>
#include <QVBoxLayout>
//5月8日，完成聊天记录的加载
//5月9日  完成消息列表和聊天记录的切换,聊天数据的定时写入
//5月10号 完成最新消息的显示以及数据库写入，在关闭时将新聊天记录立即写入后将变化了的会话写到friendlist中，并结束线程
//5月12日 完成发送文件界面的完善，文件框的调整，文件写入数据库，保存发送文件到./File,文件开头为*
QSet<QString> ChatWidget::changeset=QSet<QString>();

ChatWidget::ChatWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::ChatWidget)
{
    ui->setupUi(this);
    currentOC=QString();
    currentName=QString();
    currentitem=nullptr;
    flag=true;
    tmpcount=0;
    player=new QMediaPlayer();
    player->setVolume(100);
    enter=SettingParser::getInstance()->getValue("enter").toInt();
    newmessagering=SettingParser::getInstance()->getValue("newmessagering").toInt();
    ring=SettingParser::getInstance()->getValue("ring").toInt();
    setMedia(ring);
    ui->label_mask->setPixmap(QPixmap(":/icons/Src/Icons/Default/logoicon.png"));
    emptyChatFrame();
    //安装事件过滤器，发送区回车发送
    ui->plainTextEdit_editarea->installEventFilter(this);
    ui->listWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
    if(ContactLib::getInstance()->isEmpty())
        ThreadManger::getInstance()->loadContactListDB();
    connect(ui->listWidget->verticalScrollBar(), &QScrollBar::valueChanged, this, &ChatWidget::onScrollBarValueChanged);
    connect(ChatHistroyLib::getInstance(),&ChatHistroyLib::s_chatHistroyPageDone,this,&ChatWidget::loadChatHistroy);
    connect(FriendListLib::getInstance(),&FriendListLib::s_loadFriendDone,this,&ChatWidget::loadFriendList);
    connect(JSHandler::getInstance(),&JSHandler::s_haveNewMessage,this,&ChatWidget::loadLastestMes);
    connect(ThreadManger::getInstance(),&ThreadManger::s_haveNewFile,this,&ChatWidget::dealRecvFile);
    connect(FriendListLib::getInstance(),&FriendListLib::s_userUpdate,[=](QString oc,QString name){
        useroc=oc;
        username=name;
    });
    connect(SettingParser::getInstance(),&SettingParser::s_enter,[=](bool val){enter=val;});
    connect(SettingParser::getInstance(),&SettingParser::s_newmessagering,[=](bool val){newmessagering=val;});
    connect(SettingParser::getInstance(),&SettingParser::s_ring,[=](int val){ring=val;setMedia(ring);});
    connect(FriendListLib::getInstance(),&FriendListLib::s_lastestDone,this,[=](const QString& oc,const QString& lastest){
        if(lastest.startsWith('*'))
            friendboxlist[friendocindexlist[oc]]->setContent("[文件]");
            else
            friendboxlist[friendocindexlist[oc]]->setContent(lastest);

    });

    ThreadManger::getInstance()->loadFriendListDB();

}

ChatWidget::~ChatWidget()
{
    delete ui;
}

/*添加文本气泡*/
void ChatWidget::addMessageBox(const QString oc,const QString content,EnumLib::MessageType type,const Dir dir){
    QSize size;
    Box *box;
    //区分发送或是接受
    switch (type) {
        case EnumLib::SENDMESSAGE:
            box = new SendBox();

            break;
        case EnumLib::RECVMESSAGE:
            box = new RecvBox();
            break;
        default:
            return;
    }
    box->setText(content);
    box->setAvatar(AvatarLib::getInstance()->getAvatar(oc));
    QListWidgetItem *item=new QListWidgetItem("");
    if(dir==Dir::BACK)
        ui->listWidget->addItem(item);
    else
        ui->listWidget->insertItem(0,item);
    ui->listWidget->setItemWidget(item,box);
    size=box->getSize();
    item->setSizeHint(size);
    ui->listWidget->setCurrentRow(ui->listWidget->count()-1);
}



/*添加文件气泡*/
void ChatWidget::addFileBox(const QPixmap avatar,const QPixmap img,const QString filename,const EnumLib::MessageType type,const Dir dir)
{

    Box* filebox=nullptr;
    switch (type) {
        case EnumLib::SENDMESSAGE:
        filebox=new SendFileBox;

           break;
    case EnumLib::RECVMESSAGE:
        filebox=new RecvFileBox;
        break;
    default:
        return;
    }
    //将文件消息控件的收藏按下的信号->添加收藏
    connect(filebox,&Box::s_addFavorite,this,&ChatWidget::addFileFavorite);
    filebox->setAvatar(avatar);
    filebox->setImg(img);

    filebox->setText(filename);
    QListWidgetItem *item=new QListWidgetItem("");
    //判断插入方向
    if(dir==Dir::BACK)
        ui->listWidget->addItem(item);
    else
        ui->listWidget->insertItem(0,item);
    ui->listWidget->setItemWidget(item,filebox);
    QSize size=filebox->getSize();
    item->setSizeHint(size);
    ui->listWidget->setCurrentRow(ui->listWidget->count()-1);
}




QSet<QString> ChatWidget::getChangeSet()
{
    return changeset;
}

//设置当前会话，可提供外部接口，使好友列表跳转
void ChatWidget::setCurrentMeeting(QString oc)
{
    inChattingFrame();
    currentOC=oc;
    currentName=ContactLib::getInstance()->getName(oc);
    //定位到新好友
    int targetindex=-1;
    QString name;
    //如果消息列表不存在该对象
    if(!friendocindexlist.contains(oc))
    {
        name=ContactLib::getInstance()->getName(oc);
        //向消息列表中添加好友
        addFriendListBox(oc,name,"");
        ThreadManger::getInstance()->getFriendLastest(oc);
        ui->listWidget_friend->setCurrentRow(ui->listWidget_friend->count()-1);
        //创建聊天记录表，已做了判断存在，数据库线程不存在则创建
        ThreadManger::getInstance()->createNewChatHistroyTable(oc);
        //数据库操作，写入friendlist表
        ThreadManger::getInstance()->addToFriendList(oc,name);
    }
    else
    {
        targetindex=friendocindexlist[oc];
        FriendListBox* currentfriendbox=friendboxlist[targetindex];
        //重置会话的未读消息数
        currentfriendbox->resetCount();
        ui->listWidget_friend->setCurrentRow(targetindex);
    }

    //刷新当前会话，写入数据库
    ThreadManger::getInstance()->refreshCurMeeting(currentOC);
    //加载最新页
    ThreadManger::getInstance()->loadLastPage();
    ui->label_name->setText(currentName);
    ui->listWidget->clear();
    //设置为第一次加载
    flag=true;
    currentitem=nullptr;
    currentfrienditem=ui->listWidget_friend->item(targetindex);

}

void ChatWidget::setMedia(int val)
{
    switch(val)
    {
    case 0:
        player->setMedia(QUrl("./Audio/ring1.mp3"));
        break;
    case 1:
        player->setMedia(QUrl("./Audio/ring2.mp3"));
        break;
    default:
        break;
    }
}


//发送信息按钮
void ChatWidget::on_btn_send_clicked()
{
    if(!currentOC.isEmpty()&&!currentName.isEmpty())
    {
        //获取发送区的内容
        QString sendcontent=ui->plainTextEdit_editarea->toPlainText();
        if(sendcontent.isEmpty())
            return;
        //消息线程发送消息
        ThreadManger::getInstance()->sendMessage(useroc,currentOC,sendcontent);
        addMessageBox("user",sendcontent,EnumLib::SENDMESSAGE,Dir::BACK);
        ui->plainTextEdit_editarea->clear();
        //向新消息缓冲添加消息
        ThreadManger::getInstance()->addChat(currentOC,sendcontent,false);
        //更新好消息列表中该对象的最新消息
        friendboxlist[friendocindexlist[currentOC]]->setContent(sendcontent);
    }
    //添加到改变了的对象集合
    changeset.insert(currentOC);
}


//向好友列表中添加，注意一个box绑定一个oc和name
void ChatWidget::addFriendListBox(const QString oc,const QString name,const QString content)
{
    QListWidgetItem *item=new QListWidgetItem("");
    ui->listWidget_friend->addItem(item);
    item->setSelected(false);
    FriendListBox *box=new FriendListBox();
    ui->listWidget_friend->setItemWidget(item,box);
    ui->listWidget_friend->setCurrentItem(item);
    item->setSizeHint(QSize(ui->listWidget_friend->width(),80));
    box->setAvatar(AvatarLib::getInstance()->getAvatar(oc));
    box->setOC(oc);
    box->setNameContent(name,content);
    friendocindexlist.insert(oc,ui->listWidget_friend->count()-1);
    friendboxlist.append(box);
}

//发送文件按钮
void ChatWidget::on_btn_file_clicked()
{
    if(currentOC.isEmpty())return;
    sendfilewidget=new SendFileWidget();
    connect(sendfilewidget,SIGNAL(selectedFileDone(QStringList)),this,SLOT(sendFile(QStringList)));
    sendfilewidget->show();
}

//文本区回车发送
bool ChatWidget::eventFilter(QObject *obj, QEvent *event){
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) {
                // 检查对象是否是 QPlainTextEdit
                if (obj->inherits("QPlainTextEdit")&&enter) {
                    on_btn_send_clicked();
                    return true;
                }
            }
        }
        // 继续标准事件处理
        return QObject::eventFilter(obj, event);
}

//将消息列表中index的项移动到最顶层，在新消息到来时使用
void ChatWidget::moveItemToTop(const int index,const QString& content)
{
    //如果新消息对象已经置顶，不操作
    if(index==0)return;
    //删除原先的项
    delete ui->listWidget_friend->takeItem(index);
    //获取box信息
    FriendListBox* oldbox=friendboxlist[index];
    QString oc=oldbox->getOC();
    QString name=oldbox->getName();

    //创建新项
    QListWidgetItem *item=new QListWidgetItem("");
    ui->listWidget_friend->insertItem(0,item);
    item->setSelected(false);
    FriendListBox *box=new FriendListBox();
    ui->listWidget_friend->setItemWidget(item,box);
    item->setSizeHint(QSize(ui->listWidget_friend->width(),80));
    box->setAvatar(AvatarLib::getInstance()->getAvatar(oc));
    box->setOC(oc);
    box->setNameContent(name,content);
    if(oc==currentOC)item->setSelected(true);
    //更新维护的列表
    friendboxlist.removeAt(index);
    friendboxlist.push_front(box);
    friendocindexlist.clear();
    int m=0;
    //重新设置oc和index的表
    for(FriendListBox* i:friendboxlist)
    {
        friendocindexlist.insert(i->getOC(),m);
        m++;
    }

    delete oldbox;
}

//发送文件
void ChatWidget::sendFile(QStringList paths)
{

    QDate date=QDate::currentDate();
    // /2024-05/
    QString path=QString("/%1-%2/").arg(date.year(), 4, 10, QChar('0')).arg(date.month(), 2, 10, QChar('0'));
    for(QString p : paths)
    {
        QString lastestname;
        QFileInfo info(p);
        lastestname=info.fileName();
        QPixmap img(p);
        if(img.isNull())
        {
            img.load(":/icons/Src/Icons/Default/fileinchaticon.png");
        }
        QString newpath=checkIsExist("./User/"+useroc+"/File"+path+lastestname,lastestname,"./User/"+useroc+"/File"+path);
        addFileBox(AvatarLib::getInstance()->getAvatar("user"),img,newpath,EnumLib::SENDMESSAGE,Dir::BACK);
        //文件绝对路径    ./File/2024-05/myimg.png
        //保存发送的图片到本地
        ThreadManger::getInstance()->addSaveFile(QPair<QString,QString>(p,newpath));
        //添加发送任务到队列
        ThreadManger::getInstance()->addFileTask(useroc,currentOC,p);

    }

    changeset.insert(currentOC);
    friendboxlist[friendocindexlist[currentOC]]->setContent("[文件]");
}

//发送相机拍摄的照片
void ChatWidget::sendCameraPhoto(QImage image)
{
    addFileBox(QPixmap(":/icons/Src/Img/avatar.jpg"),QPixmap::fromImage(image),"相机",EnumLib::SENDMESSAGE,Dir::BACK);
}

//相机按钮
void ChatWidget::on_btn_camera_clicked()
{
    if(currentOC.isEmpty())return;
    camerawidget=new CameraWidget;
    camerawidget->show();
    //将相机窗口获取的图片添加到聊天窗口
    connect(camerawidget,&CameraWidget::sendCameraPhoto,this,&ChatWidget::sendCameraPhoto);
}

//滚轮值变化的槽，为了上划到顶部时触发加载更多记录
void ChatWidget::onScrollBarValueChanged(int value)
{
    if (value == ui->listWidget->verticalScrollBar()->minimum()&&ui->listWidget->count())
    {
        ThreadManger::getInstance()->loadLastPage();
    }
}

//在chathistroylib加载记录完毕信号时调用，将其记录加载到界面
void ChatWidget::loadChatHistroy()
{
    if(ui->listWidget->count())
        currentitem=ui->listWidget->item(0);
    //<oc,content>
    //文件前缀*
    QList<QPair<bool,QString>> result;

    result=ChatHistroyLib::getInstance()->getChatHistroyList();
    for(int i=result.size()-1;i>=0;i--)
    {
        if(result[i].second[0]!='*')
        {
            if(result[i].first)
            {
                addMessageBox(currentOC,result[i].second.toUtf8(),EnumLib::RECVMESSAGE,Dir::FRONT);
            }
            else
            {

                addMessageBox("user",result[i].second.toUtf8(),EnumLib::SENDMESSAGE,Dir::FRONT);
            }
        }
        else
        {
            QString file=result[i].second.mid(1);
            //  /2024-02/xxx.png
            QString sendfilepath="./User/"+useroc+"/File"+file;
            QString recvfilepath="./User/"+useroc+"/RecvFile"+file;

            QPixmap img;
            if(result[i].first)
                img=QPixmap(recvfilepath);
            else
                img=QPixmap(sendfilepath);
            if(img.isNull())
                img.load(":/icons/Src/Icons/Default/fileinchaticon.png");
            if(result[i].first)
            {
                addFileBox(AvatarLib::getInstance()->getAvatar(currentOC),img,recvfilepath,EnumLib::RECVMESSAGE,Dir::FRONT);
            }
            else
            {
                addFileBox(AvatarLib::getInstance()->getAvatar(currentOC),img,sendfilepath,EnumLib::SENDMESSAGE,Dir::FRONT);
            }
        }
    }
    //判断是否为第一次加载
   if(flag)
   {
       //滑到底部
       if(ui->listWidget->verticalScrollBar())
       {
            ui->listWidget->scrollToItem(ui->listWidget->item(ui->listWidget->count()-1));
           flag=false;
       }
   }
   if(currentitem)
        ui->listWidget->setCurrentItem(currentitem);
}

void ChatWidget::loadFriendList()
{
    ui->listWidget_friend->clear();
    friendocindexlist.clear();
    friendboxlist.clear();
    QList<QPair<QPair<QString,QString>,QString>> result=FriendListLib::getInstance()->getList();
    for(QPair<QPair<QString,QString>,QString> i:result)
    {
        if(i.second[0]=='*')
            addFriendListBox(i.first.first,i.first.second,"[文件]");
        else
            addFriendListBox(i.first.first,i.first.second,i.second);
    }
    ui->listWidget_friend->clearSelection();
    //userInfo=FriendListLib::getInstance()->getUserInfo();
    //用户oc及用户名存储在friendlist表中，取出oc及名称来维护
    username=FriendListLib::getInstance()->getUserName();
    useroc=FriendListLib::getInstance()->getUserOC();
}


//好友列表点击，代表进入一个新的会话
void ChatWidget::on_listWidget_friend_itemClicked(QListWidgetItem *item)
{
    //加载聊天记录流程  设置chathistroylib的oc号-》调用loadLastPage-》就绪，加载
    //防止重复点击
    inChattingFrame();
    if(currentfrienditem==nullptr)
        currentfrienditem=item;
    else if(item==currentfrienditem)
        return;
    FriendListBox* currentfriendbox=friendboxlist[ui->listWidget_friend->row(item)];
    emit s_subCount(currentfriendbox->getCount());
    currentfriendbox->resetCount();
    currentOC=currentfriendbox->getOC();
    currentName=currentfriendbox->getName();
    ThreadManger::getInstance()->refreshCurMeeting(currentOC);
    ui->label_name->setText(currentName);
    ui->listWidget->clear();
    //设置为第一次加载
    flag=true;
    ThreadManger::getInstance()->loadLastPage();
    currentitem=nullptr;
    currentfrienditem=item;
    currentfilebox=nullptr;
    //disconnect(ThreadManger::getInstance(),&ThreadManger::s_speed,currentfilebox,&SendFileBox::setProcess);
}


//有新消息
void ChatWidget::loadLastestMes(QPair<QString, QString> res)
{
    QString senderoc=res.first;
    if(newmessagering)player->play();
    //当前会话不为目标对象
    if(currentOC!=senderoc)
    {
        if(!friendocindexlist.contains(senderoc))
        {
            ThreadManger::getInstance()->createNewChatHistroyTable(senderoc);
            addFriendListBox(senderoc,ContactLib::getInstance()->getName(senderoc),res.second);
            ThreadManger::getInstance()->addToFriendList(senderoc,ContactLib::getInstance()->getName(senderoc),res.second);
        }
        moveItemToTop(friendocindexlist.value(senderoc),res.second);
        friendboxlist[friendocindexlist.value(senderoc)]->raiseCount();
        emit s_addCount();
    }
    //为目标对象
    else
    {
        addMessageBox(currentOC,res.second,EnumLib::RECVMESSAGE,Dir::BACK);
        moveItemToTop(friendocindexlist[senderoc],res.second);
        //临时变量存储当前会话的消息数
        if(!PageManger::currentIsChat())
        {
            tmpcount++;
            emit s_addCount();
        }
    }
    friendboxlist[friendocindexlist[senderoc]]->setContent(res.second);
    //mian窗口消息数+1

}


//传入 ./File/2024-05/myimg.png    myimg.png    ./File/2024-05/
QString ChatWidget::checkIsExist(QString filepath,QString filename,QString lastpath)
{
    int count=1;
    QString tmp;
    QString newpath=filepath;
    QFile file(filepath);
    while(file.exists()){
        tmp=filename;
        //destinationFilePath=QString(dirpath+"["+QString::number(count++)+"]"+filename);
        newpath=QString("%1[%2]%3").arg(lastpath).arg(count++).arg(tmp);
        file.setFileName(newpath);
    }
    return newpath;
}

//oc filepath
void ChatWidget::dealRecvFile(const QString& friendoc,const QString& content)
{
    if(currentOC!=friendoc)
    {
        friendboxlist[friendocindexlist[friendoc]]->raiseCount();
    }
    else
    {
        QString filepath="./User/"+useroc+"/RecvFile/"+content.mid(1);
        qDebug()<<"recvfilepath  "<<filepath;
        QPixmap img(filepath);
        if(img.isNull())
        {
            img.load(":/icons/Src/Icons/Default/fileinchaticon.png");
        }
        addFileBox(AvatarLib::getInstance()->getAvatar(currentOC),img,filepath.mid(32),EnumLib::RECVMESSAGE,Dir::BACK);
    }
    friendboxlist[friendocindexlist[friendoc]]->setContent("[文件]");
    changeset.insert(friendoc);

}

void ChatWidget::on_listWidget_customContextMenuRequested(const QPoint &pos)
{
        QMenu menu(this);
        QAction* open=menu.addAction("打开");
        QAction* del= menu.addAction("移除");
        QAction* openinpath=menu.addAction("在文件管理器中打开");
        ui->listWidget->itemAt(pos)->setSelected(true);
        connect(del,&QAction::triggered,this,[=](){
        });

        connect(open,&QAction::triggered,this,[=](){
            qDebug()<<"open";
        });
        connect(openinpath,&QAction::triggered,this,[=](){
            qDebug()<<"openinpath";
        });


        menu.exec(QCursor::pos());
}

void ChatWidget::addFileFavorite(QString filepath, QString filename, QString datetime)
{
    //保存收藏的文件
    ThreadManger::getInstance()->saveFavorite(QPair<QString,QString>(filepath,"./FavoriteFile/"+filename));
    //添加到数据库
    ThreadManger::getInstance()->addFavorite(currentOC,"*"+filename,datetime);
}

int ChatWidget::getTmpCount()
{
    int count=tmpcount;
    tmpcount=0;
    return count;
}

void ChatWidget::removeFriend(const QStringList& friendoclist)
{
    loadFriendList();
    for(QString i:friendoclist)
    {
        if(changeset.contains(i))changeset.remove(i);
    }
}

void ChatWidget::clearAll()
{
    friendboxlist.clear();
    friendocindexlist.clear();
    if(changeset.contains(currentOC))
        changeset.remove(currentOC);
    ui->listWidget->clear();
    currentOC=QString();
    currentName=QString();
    currentitem=nullptr;
    currentfrienditem=nullptr;
}

void ChatWidget::on_listWidget_friend_customContextMenuRequested(const QPoint &pos)
{
    QMenu menu(ui->listWidget_friend);
    QAction* hideChat=menu.addAction("不显示此会话");
    QAction* deleteChat=menu.addAction("删除会话");
    connect(hideChat,&QAction::triggered,this,&ChatWidget::hideChat);
    connect(deleteChat,&QAction::triggered,this,&ChatWidget::deleteChat);
    menu.exec(QCursor::pos());
}

void ChatWidget::hideChat()
{
    emptyChatFrame();
    ThreadManger::getInstance()->deleteFriendRowAndLoad(currentOC);
    clearAll();
}

void ChatWidget::deleteChat()
{
    emptyChatFrame();
    ThreadManger::getInstance()->deleteDropFriendAndLoad(currentOC);
    clearAll();
}

void ChatWidget::emptyChatFrame()
{
    ui->label_name->clear();
    ui->label_mask->show();
    ui->frame->hide();
}

void ChatWidget::inChattingFrame()
{
    if(ui->frame->isVisible())return;
    ui->label_mask->hide();
    ui->frame->show();
}



